#include <cstdio>
#include <cstring>
#include <unistd.h>
#include <cassert>
#include <sys/types.h>
#include <cstdlib>
#include <sys/wait.h>
#include <iostream>

#define BUFFER_SIZE 1024 //缓冲区大小

int main()
{
    //todo：创建匿名管道文件，该管道文件为内存级文件，可以传递给子进程
    int pipefd[2] = {0};
    int ret = pipe(pipefd);
    assert(ret == 0);

    //todo：创建子进程，让父子进程通过管道进行通信
    pid_t id = fork();
    assert(id >= 0);

    //这里让子进程发送数据，父进程接受数据
    //* 管道是单向的 pipefd[0]是输出端，pipe[1]是输入端
    if (id == 0) //子进程
    {
        int ret = close(pipefd[0]); //关闭输出端
        assert(ret == 0);

        const char* s = "i am child and i am sending messeage to you now!";
        int cnt = 0;
        while (true)
        {
            char buffer[BUFFER_SIZE] = {};
            std::snprintf(buffer, sizeof buffer/*sizeof(buffer)*/, 
                "child said to parent: %s[%d][%d]", s, cnt++, getpid());

            write(pipefd[1], buffer, std::strlen(buffer));

            sleep(1);
        }

        //使用完后关闭管道输入端
        ret = close(pipefd[1]);
        assert(ret == 0);

        exit(0);
    }

    //父进程
    ret = close(pipefd[1]); //关闭输入端
    assert(ret == 0);

    while (true)
    {
        char buffer[BUFFER_SIZE] = {};

        ssize_t len = read(pipefd[0], buffer, sizeof(buffer) - 1);

        if (len > 0)
        {
            buffer[len] = '\0';
            std::cout 
                << "parent get messgae: " << buffer 
                << " | " << "parent pid is: " << getpid()
                << std::endl;
        }
        else if (len == 0)
        {
            std::cout << "task completed!" << std::endl;
            break;
        }
        else
        {
            assert(false);
        }
    }

    ret = close(pipefd[0]);
    assert(ret == 0);

    int status = 0;
    pid_t ret_id = waitpid(id, &status, 0);
    assert(ret_id == id);

    std::cout 
        << "child's pid->" << ret_id 
        << "it's exit code->" << ((status >> 8) & 0XFF)
        << "it's signal->" << (status & 0X7F)
        << std::endl;

    return 0;
}